เพิ่มประสิทธิภาพความเร็วในการคอมไพล์ TypeScript ด้วยเทคนิคที่พิสูจน์แล้ว เรียนรู้วิธีปรับปรุงเวิร์กโฟลว์การพัฒนาและลดเวลาการสร้างเพื่อการทำงานที่รวดเร็วขึ้น
ประสิทธิภาพของ TypeScript: เทคนิคการเพิ่มประสิทธิภาพความเร็วในการคอมไพล์
TypeScript ซึ่งเป็นชุดย่อยของ JavaScript ให้การพิมพ์แบบคงที่ การจัดระเบียบโค้ดที่ดีขึ้น และการบำรุงรักษาที่ดีขึ้น อย่างไรก็ตาม เมื่อโปรเจ็กต์มีขนาดและความซับซ้อนมากขึ้น การคอมไพล์ TypeScript อาจกลายเป็นปัญหาคอขวดที่สำคัญในเวิร์กโฟลว์การพัฒนา เวลาในการคอมไพล์ที่ช้าอาจนำไปสู่การลดลงของประสิทธิภาพการทำงานของนักพัฒนา ความหงุดหงิดที่เพิ่มขึ้น และรอบการทำงานที่ยาวนานขึ้น บทความนี้เจาะลึกเทคนิคที่มีประสิทธิภาพสำหรับการเพิ่มประสิทธิภาพความเร็วในการคอมไพล์ TypeScript เพื่อให้มั่นใจถึงประสบการณ์การพัฒนาที่ราบรื่นและมีประสิทธิภาพมากขึ้น
ทำความเข้าใจเกี่ยวกับกระบวนการคอมไพล์
ก่อนที่จะเจาะลึกเทคนิคการเพิ่มประสิทธิภาพ สิ่งสำคัญคือต้องเข้าใจกระบวนการคอมไพล์ TypeScript ตัวคอมไพเลอร์ TypeScript (tsc) จะอ่านไฟล์ TypeScript ดำเนินการตรวจสอบประเภท และปล่อยไฟล์ JavaScript ปัจจัยหลายประการมีอิทธิพลต่อความเร็วในการคอมไพล์ ซึ่งรวมถึง:
- ขนาดโปรเจ็กต์: จำนวนไฟล์ TypeScript และบรรทัดของโค้ดส่งผลกระทบโดยตรงต่อเวลาในการคอมไพล์
- ความซับซ้อนของประเภท: การกำหนดประเภทที่ซับซ้อน, generics และ union จะเพิ่มภาระงานของคอมไพเลอร์
- การแก้ไขโมดูล: กระบวนการค้นหาและแก้ไขการอ้างอิงโมดูลอาจใช้เวลานาน โดยเฉพาะอย่างยิ่งในโปรเจ็กต์ขนาดใหญ่ที่มีโครงสร้างโมดูลที่ซับซ้อน
- การกำหนดค่า tsconfig.json: ตัวเลือกคอมไพเลอร์ที่ระบุในไฟล์
tsconfig.jsonส่งผลกระทบอย่างมากต่อความเร็วและเอาต์พุตการคอมไพล์ - ฮาร์ดแวร์: ความเร็วของ CPU, RAM และประสิทธิภาพ I/O ของดิสก์ก็มีบทบาทเช่นกัน
เทคนิคการเพิ่มประสิทธิภาพ
นี่คือเทคนิคหลายประการในการเพิ่มประสิทธิภาพความเร็วในการคอมไพล์ TypeScript:
1. การคอมไพล์แบบเพิ่มหน่วย
การคอมไพล์แบบเพิ่มหน่วยเป็นหนึ่งในวิธีที่มีประสิทธิภาพที่สุดในการปรับปรุงความเร็วในการคอมไพล์ เมื่อเปิดใช้งาน คอมไพเลอร์จะแคชข้อมูลเกี่ยวกับโครงสร้างและการอ้างอิงของโปรเจ็กต์ การคอมไพล์ครั้งต่อๆ ไปจะประมวลผลเฉพาะไฟล์ที่เปลี่ยนแปลงตั้งแต่การคอมไพล์ครั้งล่าสุด หากต้องการเปิดใช้งานการคอมไพล์แบบเพิ่มหน่วย ให้ตั้งค่าตัวเลือก incremental เป็น true ในไฟล์ tsconfig.json ของคุณ:
{
"compilerOptions": {
"incremental": true,
"tsBuildInfoFile": ".tsbuildinfo" // Optional, but recommended
}
}
ตัวเลือก tsBuildInfoFile ระบุตำแหน่งของไฟล์ข้อมูลการสร้างแบบเพิ่มหน่วย เป็นแนวทางปฏิบัติที่ดีในการรวมไฟล์นี้ใน .gitignore ของคุณเพื่อป้องกันไม่ให้ถูกติดตามโดย Git
ตัวอย่าง: ลองนึกภาพแอปพลิเคชันอีคอมเมิร์ซขนาดใหญ่ที่มีไฟล์ TypeScript หลายร้อยไฟล์ หากไม่มีการคอมไพล์แบบเพิ่มหน่วย การสร้างทั้งหมดอาจใช้เวลาหลายนาที เมื่อเปิดใช้งานการคอมไพล์แบบเพิ่มหน่วย การสร้างครั้งต่อๆ ไปหลังจากมีการเปลี่ยนแปลงโค้ดเล็กน้อยอาจใช้เวลาเพียงไม่กี่วินาที
2. การอ้างอิงโครงการ
สำหรับโปรเจ็กต์ขนาดใหญ่ ให้พิจารณาแบ่งออกเป็นโมดูลหรือไลบรารีขนาดเล็กที่จัดการได้ง่ายขึ้น คุณสมบัติการอ้างอิงโครงการของ TypeScript ช่วยให้คุณสามารถจัดโครงสร้างโค้ดเบสของคุณเป็นชุดของโครงการที่เชื่อมต่อถึงกัน ซึ่งช่วยให้คอมไพเลอร์สามารถสร้างโปรเจ็กต์แบบขนานและแบบเพิ่มหน่วย ซึ่งช่วยลดเวลาในการสร้างได้มากขึ้น
ในการใช้การอ้างอิงโครงการ ให้สร้างไฟล์ tsconfig.json สำหรับแต่ละโครงการย่อย ใน tsconfig.json ของโครงการหลัก ให้เพิ่มอาร์เรย์ references ที่แสดงรายการเส้นทางไปยังไฟล์ tsconfig.json ของโครงการย่อย:
{
"compilerOptions": {
"composite": true, // Required for project references
"declaration": true, // Required for project references
"declarationMap": true,
"incremental": true,
"tsBuildInfoFile": ".tsbuildinfo"
},
"files": [], // Explicitly exclude files; include using `references`
"references": [
{ "path": "./core" },
{ "path": "./ui" },
{ "path": "./api" }
]
}
tsconfig.json ของแต่ละโครงการที่อ้างอิงต้องมี composite: true และ declaration: true ซึ่งช่วยให้ TypeScript สร้างไฟล์ประกาศ (.d.ts) สำหรับแต่ละโครงการย่อย ซึ่งใช้โดยโครงการอื่นๆ ที่ขึ้นอยู่กับโครงการเหล่านั้น
ตัวอย่าง: พิจารณาเว็บแอปพลิเคชันที่มีไลบรารีหลัก ไลบรารี UI และไลบรารีไคลเอนต์ API แต่ละไลบรารีสามารถเป็นโปรเจ็กต์แยกต่างหากที่มี tsconfig.json ของตัวเองได้ จากนั้นโปรเจ็กต์แอปพลิเคชันหลักสามารถอ้างอิงไลบรารีเหล่านี้ได้ ซึ่งช่วยให้ TypeScript สร้างไลบรารีเหล่านี้แยกกันและขนานกันได้
3. กลยุทธ์การแก้ไขโมดูล
กลยุทธ์การแก้ไขโมดูลของ TypeScript จะกำหนดว่าคอมไพเลอร์ค้นหาและแก้ไขการอ้างอิงโมดูลอย่างไร กลยุทธ์เริ่มต้น classic อาจไม่มีประสิทธิภาพ โดยเฉพาะอย่างยิ่งในโปรเจ็กต์ขนาดใหญ่ การเปลี่ยนไปใช้กลยุทธ์การแก้ไขโมดูล node สามารถปรับปรุงความเร็วในการคอมไพล์ได้อย่างมาก
ในการใช้กลยุทธ์การแก้ไขโมดูล node ให้ตั้งค่าตัวเลือก moduleResolution เป็น node ในไฟล์ tsconfig.json ของคุณ:
{
"compilerOptions": {
"moduleResolution": "node"
}
}
กลยุทธ์การแก้ไขโมดูล node เลียนแบบอัลกอริธึมการแก้ไขโมดูลของ Node.js ซึ่งโดยทั่วไปแล้วจะมีประสิทธิภาพและคาดเดาได้มากกว่า
นอกจากนี้ การตรวจสอบให้แน่ใจว่าคุณกำลังใช้ตัวเลือกคอมไพเลอร์ `baseUrl` และ `paths` อย่างถูกต้องสามารถเพิ่มความเร็วในการแก้ไขโมดูลได้อย่างมาก `baseUrl` ระบุไดเรกทอรีฐานในการแก้ไขชื่อโมดูลที่ไม่สัมบูรณ์ `paths` ช่วยให้คุณสร้างนามแฝงสำหรับเส้นทางโมดูลได้
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@core/*": ["src/core/*"],
"@ui/*": ["src/ui/*"]
}
}
}
ตัวอย่าง: โปรเจ็กต์อาจมีไดเรกทอรีโมดูลที่ซ้อนกันอย่างลึกซึ้ง การใช้ baseUrl และ paths สามารถหลีกเลี่ยงเส้นทางสัมพัทธ์ที่ยาว (เช่น ../../../../utils/helpers) และทำให้การแก้ไขโมดูลเร็วขึ้น
4. การคอมไพล์แบบกำหนดเป้าหมาย
แทนที่จะคอมไพล์ทั้งโปรเจ็กต์ทุกครั้ง คุณสามารถกำหนดเป้าหมายไฟล์หรือไดเรกทอรีเฉพาะได้ สิ่งนี้มีประโยชน์อย่างยิ่งในระหว่างการพัฒนาเมื่อคุณทำงานกับชุดย่อยเล็กๆ ของโค้ดเบสเท่านั้น ใช้บรรทัดคำสั่ง `tsc` เพื่อกำหนดเป้าหมายไฟล์เฉพาะ
tsc src/components/MyComponent.ts
สิ่งนี้จะคอมไพล์เฉพาะ `MyComponent.ts` และการอ้างอิงเท่านั้น
ด้วยการอ้างอิงโครงการ คุณสามารถคอมไพล์โปรเจ็กต์ย่อยแต่ละรายการได้:
tsc -b core
คำสั่งนี้จะคอมไพล์โปรเจ็กต์ `core` ที่กำหนดไว้ในอาร์เรย์ references ของคุณ
5. ลดค่าใช้จ่ายในการตรวจสอบประเภท
แม้ว่าการพิมพ์แบบคงที่ของ TypeScript จะเป็นข้อได้เปรียบที่สำคัญ แต่ก็สามารถมีส่วนช่วยในการเพิ่มค่าใช้จ่ายในการคอมไพล์ คุณสมบัติบางอย่าง เช่น generics และ union ที่ซับซ้อน อาจมีค่าใช้จ่ายสูงเป็นพิเศษในการตรวจสอบประเภท พิจารณาแนวทางปฏิบัติเหล่านี้:
- ใช้ประเภทที่ชัดเจน: การกำหนดประเภทอย่างชัดเจนบางครั้งสามารถช่วยให้คอมไพเลอร์อนุมานประเภทได้อย่างมีประสิทธิภาพมากขึ้น
- หลีกเลี่ยง Generics ที่มากเกินไป: การใช้ generics มากเกินไปอาจนำไปสู่การอนุมานประเภทที่ซับซ้อน พิจารณาใช้ประเภทที่เฉพาะเจาะจงมากขึ้นเมื่อเป็นไปได้
- ลดความซับซ้อนของประเภท Union: ประเภท union ขนาดใหญ่อาจมีค่าใช้จ่ายสูงในการตรวจสอบ พิจารณาใช้ discriminated unions หรือเทคนิคอื่นๆ เพื่อลดความซับซ้อนของการกำหนดประเภท
- ใช้ `any` (ด้วยความระมัดระวัง): แม้ว่าจะไม่แนะนำโดยทั่วไป แต่การใช้ `any` สามารถข้ามการตรวจสอบประเภทในสถานการณ์เฉพาะที่ประสิทธิภาพมีความสำคัญ และความปลอดภัยของประเภทมีความสำคัญน้อยกว่า อย่างไรก็ตาม ใช้สิ่งนี้อย่างระมัดระวัง เนื่องจากเป็นการทำลายจุดประสงค์ของการใช้ TypeScript
- `--noImplicitAny`: การตั้งค่าแฟล็กนี้เป็น `true` ใน `tsconfig.json` จะบังคับให้คุณใส่คำอธิบายประกอบประเภทอย่างชัดเจน ซึ่งสามารถช่วยคอมไพเลอร์ในการอนุมานประเภทได้
ตัวอย่าง: แทนที่จะใช้ประเภททั่วไป เช่น Array<T> ที่ T สามารถเป็นอะไรก็ได้ ให้พิจารณาใช้ประเภทที่เฉพาะเจาะจงมากขึ้น เช่น Array<string> หรือ Array<number> หากทราบว่าอาร์เรย์มีเฉพาะสตริงหรือตัวเลข
6. การเพิ่มประสิทธิภาพตัวเลือกคอมไพเลอร์
ตัวเลือกคอมไพเลอร์หลายรายการใน tsconfig.json สามารถส่งผลกระทบต่อความเร็วในการคอมไพล์ พิจารณาปรับตัวเลือกเหล่านี้เพื่อเพิ่มประสิทธิภาพ:
- `target`: เลือกเวอร์ชัน JavaScript เป้าหมายที่สอดคล้องกับสภาพแวดล้อมรันไทม์ของคุณ การกำหนดเป้าหมายเวอร์ชันเก่า (เช่น
ES5) อาจต้องมีการแปลงโค้ดเพิ่มเติม ซึ่งเพิ่มเวลาในการคอมไพล์ การกำหนดเป้าหมายเวอร์ชันใหม่กว่า (เช่น `ES2020`, `ESNext`) อาจส่งผลให้การคอมไพล์เร็วขึ้น - `module`: ระบุสไตล์การสร้างโค้ดโมดูล (เช่น
commonjs,esnext,amd) `esnext` มักจะเร็วกว่าสำหรับ bundlers สมัยใหม่ - `sourceMap`: ปิดใช้งานการสร้าง source map ในการสร้างโปรดักชั่นเพื่อลดเวลาในการคอมไพล์และขนาดเอาต์พุต ตั้งค่า
sourceMapเป็นfalseในtsconfig.jsonสำหรับโปรดักชั่นของคุณ - `declaration`: เปิดใช้งานการสร้างไฟล์ประกาศ (
.d.ts) เมื่อจำเป็นเท่านั้น ปิดใช้งานสำหรับบิวด์การพัฒนาหากคุณไม่จำเป็นต้องสร้างไฟล์ประกาศ - `removeComments`: การลบคอมเมนต์ในระหว่างการคอมไพล์สามารถปรับปรุงเวลาในการสร้างและลดขนาดเอาต์พุตได้เล็กน้อย ตั้งค่า
removeCommentsเป็นtrue - `importHelpers`: การใช้ไลบรารีตัวช่วย (เช่น `tslib`) จะหลีกเลี่ยงการแทรกฟังก์ชันตัวช่วยลงในแต่ละโมดูล ซึ่งสามารถลดขนาดโค้ดและเวลาในการคอมไพล์ได้ ตั้งค่า `importHelpers` เป็น `true` และติดตั้ง `tslib`
- `isolatedModules`: หากคุณใช้เครื่องมือเช่น Babel สำหรับการแปลง *ก่อน* TypeScript การตั้งค่าแฟล็กนี้เป็น `true` จะบังคับให้แต่ละไฟล์สามารถคอมไพล์เป็นโมดูลแยกกันได้ สิ่งนี้สามารถช่วยให้สร้างได้เร็วขึ้นในบางสถานการณ์
ตัวอย่าง: สำหรับเว็บแอปพลิเคชันสมัยใหม่ที่กำหนดเป้าหมายเบราว์เซอร์ล่าสุด คุณอาจใช้ "target": "ESNext" และ "module": "esnext"
7. ใช้ประโยชน์จากเครื่องมือสร้างและ bundlers
เครื่องมือต่างๆ เช่น Webpack, Rollup และ Parcel สามารถปรับปรุงประสิทธิภาพการสร้าง TypeScript ได้อย่างมาก เครื่องมือเหล่านี้ใช้เทคนิคการเพิ่มประสิทธิภาพต่างๆ เช่น:
- Tree Shaking: กำจัดโค้ดที่ไม่ได้ใช้เพื่อลดขนาดเอาต์พุต
- Code Splitting: แบ่งแอปพลิเคชันออกเป็นส่วนย่อยขนาดเล็กที่สามารถโหลดได้ตามต้องการ
- Caching: แคชผลลัพธ์การสร้างเพื่อหลีกเลี่ยงการคอมไพล์ซ้ำซ้อน
- Parallelization: รันงานสร้างแบบขนานเพื่อใช้ประโยชน์จากคอร์ CPU หลายตัว
เมื่อรวม TypeScript เข้ากับเครื่องมือสร้าง ให้พิจารณาใช้ปลั๊กอินและตัวโหลดที่ออกแบบมาโดยเฉพาะสำหรับ TypeScript เช่น ts-loader หรือ esbuild-loader สำหรับ Webpack หรือการสนับสนุน TypeScript ในตัวใน Parcel เครื่องมือเหล่านี้มักจะเสนอตัวเลือกการเพิ่มประสิทธิภาพเพิ่มเติมและการรวมเข้ากับเครื่องมือสร้างอื่นๆ
ตัวอย่าง: การใช้ Webpack กับ ts-loader และการเปิดใช้งานการแคชสามารถลดเวลาในการสร้างสำหรับเว็บแอปพลิเคชันขนาดใหญ่ได้อย่างมาก การสร้างครั้งแรกอาจใช้เวลานานกว่า แต่การสร้างครั้งต่อๆ ไปจะเร็วขึ้นมากเนื่องจากการแคช
8. ใช้ Transpilers/Checkers ที่เร็วกว่า
tsc อย่างเป็นทางการไม่ใช่ตัวเลือกที่เร็วที่สุดเสมอไป พิจารณาทางเลือกอื่น เช่น:
- esbuild: JavaScript และ TypeScript bundler และ transpiler ที่รวดเร็วมาก ซึ่งเขียนด้วย Go อาจเร็วกว่า `tsc` อย่างมากสำหรับการแปลง แม้ว่าจะไม่สามารถให้ระดับความเข้มงวดในการตรวจสอบประเภทได้ก็ตาม
- swc: เครื่องมืออื่นที่ใช้ Rust ซึ่งเร็วอย่างเหลือเชื่อสำหรับการแปลงและ bundling
- ts-patch + @typescript-eslint/typescript-estree: หากโปรเจ็กต์ของคุณพึ่งพา ESLint และ `@typescript-eslint` เป็นอย่างมาก การรวมกันนี้มักจะช่วยเร่งกระบวนการ linting ของคุณโดยการแพตช์ TypeScript เพื่อใช้ AST ที่มีประสิทธิภาพมากขึ้น
บ่อยครั้ง วิธีการที่ดีที่สุดคือการใช้ชุดค่าผสม: ใช้ `tsc` สำหรับการตรวจสอบประเภทในกระบวนการแยกต่างหาก (หรือใน IDE ของคุณ) จากนั้นใช้ `esbuild` หรือ `swc` สำหรับการแปลงและการ bundling จริง
9. ตรวจสอบและประเมินความเร็วในการคอมไพล์
ตรวจสอบและประเมินความเร็วในการคอมไพล์ TypeScript ของคุณเป็นประจำ เพื่อระบุปัญหาคอขวดและติดตามประสิทธิผลของความพยายามในการเพิ่มประสิทธิภาพของคุณ ใช้เครื่องมือเช่นแฟล็ก --diagnostics ใน tsc เพื่อรับข้อมูลโดยละเอียดเกี่ยวกับเวลาในการคอมไพล์
tsc --diagnostics
สิ่งนี้จะแสดงข้อมูลเกี่ยวกับเวลาที่ใช้ไปในขั้นตอนต่างๆ ของกระบวนการคอมไพล์ เช่น การแยกวิเคราะห์ การตรวจสอบประเภท และการสร้างโค้ด คุณสามารถใช้ข้อมูลนี้เพื่อระบุส่วนที่ความพยายามในการเพิ่มประสิทธิภาพมีแนวโน้มที่จะส่งผลกระทบอย่างมีนัยสำคัญ
ตัวอย่าง: หากรายงานการวินิจฉัยแสดงให้เห็นว่าการตรวจสอบประเภทใช้เวลามาก คุณอาจมุ่งเน้นไปที่การลดความซับซ้อนของการกำหนดประเภท หรือลดการใช้ generics ที่ซับซ้อน
10. เพิ่มประสิทธิภาพ IDE และ Editor ของคุณ
IDE หรือโปรแกรมแก้ไขของคุณอาจส่งผลกระทบต่อประสิทธิภาพที่เห็นได้ชัดเจนเช่นกัน ตรวจสอบให้แน่ใจว่าคุณใช้ IDE และปลั๊กอิน TypeScript เวอร์ชันล่าสุด กำหนดค่า IDE ของคุณเพื่อใช้ TypeScript เวอร์ชันของโปรเจ็กต์ แทนที่จะเป็นเวอร์ชันสากล พิจารณาปิดใช้งานคุณสมบัติ เช่น การตรวจสอบประเภทอัตโนมัติ หรือการเติมโค้ดอัตโนมัติ หากทำให้เวิร์กโฟลว์ของคุณช้าลง
บทสรุป
การเพิ่มประสิทธิภาพความเร็วในการคอมไพล์ TypeScript เป็นสิ่งสำคัญสำหรับการรักษาเวิร์กโฟลว์การพัฒนาที่มีประสิทธิภาพและประสิทธิผล ด้วยการใช้เทคนิคที่อธิบายไว้ในบทความนี้ คุณสามารถลดเวลาในการสร้างได้อย่างมาก ปรับปรุงความพึงพอใจของนักพัฒนา และเร่งการส่งมอบซอฟต์แวร์คุณภาพสูง อย่าลืมตรวจสอบและประเมินความเร็วในการคอมไพล์ของคุณอย่างต่อเนื่อง เพื่อระบุส่วนที่ต้องการการเพิ่มประสิทธิภาพเพิ่มเติม และตรวจสอบให้แน่ใจว่าความพยายามของคุณส่งผลกระทบตามที่ต้องการ กลยุทธ์การเพิ่มประสิทธิภาพที่ดีที่สุดมักจะเป็นการผสมผสานเทคนิคหลายอย่างที่ปรับให้เหมาะกับโปรเจ็กต์และสภาพแวดล้อมการพัฒนาของคุณ